<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   
      <title>4.4. Control de la Navegaci&oacute;n. Saltando entre ventanas</title>
      <meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2">
      <link rel="home" href="indice.html" title="Manual Usuario gvHidra">
      <link rel="up" href="ch04.html" title="Cap&iacute;tulo 4. Elementos de pantalla avanzados">
      <link rel="prev" href="ch04s03.html" title="4.3. Tratamiento de ficheros">
      <link rel="next" href="ch04s05.html" title="4.5. Carga din&aacute;mica de clases">
   </head>
   <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
      <div class="navheader">
         <table width="100%" summary="Navigation header">
            <tr>
               <th colspan="3" align="center">4.4. Control de la Navegaci&oacute;n. Saltando entre ventanas</th>
            </tr>
            <tr>
               <td width="20%" align="left"><a accesskey="p" href="ch04s03.html">Anterior</a>&nbsp;
               </td>
               <th width="60%" align="center">Cap&iacute;tulo 4. Elementos de pantalla avanzados</th>
               <td width="20%" align="right">&nbsp;<a accesskey="n" href="ch04s05.html">Siguiente</a></td>
            </tr>
         </table>
         <hr>
      </div>
      <div class="section" title="4.4. Control de la Navegaci&oacute;n. Saltando entre ventanas">
         <div class="titlepage">
            <div>
               <div>
                  <h2 class="title" style="clear: both"><a name="d4e3778"></a>4.4. Control de la Navegaci&oacute;n. Saltando entre ventanas
                  </h2>
               </div>
            </div>
         </div>
             
         
             
         <p>Uno de los t&iacute;picos problemas en el dise&ntilde;o de aplicaciones web es el
                control de la navegaci&oacute;n. Para ayudar en la resoluci&oacute;n de este problema,
                el framework incorpora un mecanismo que facilita el uso de estos saltos
                entre p&aacute;ginas con el consiguiente paso de mensajes.
         </p>
         
             
         <p>Para entender la problem&aacute;tica que implica los saltos entre p&aacute;ginas,
                vamos a destacar ciertos puntos que se deben considerar:
         </p>
         
             
         <div class="itemizedlist">
            <ul class="itemizedlist" type="disc">
               <li class="listitem">
                          
                  <p><span class="bold"><strong>Paso de par&aacute;metros</strong></span>:
                             evidentemente, se debe poder pasar informaci&oacute;n desde el origen hasta
                             el destino. En nuestro caso desde una clase manejadora a otra. Para
                             ello, tenemos que hacer uso de la SESSION.
                  </p>
                        
               </li>
               <li class="listitem">
                          
                  <p><span class="bold"><strong>Pila de saltos</strong></span>: de alguna
                             manera, una vez volvamos de un salto debemos limpiar todo rastro del
                             salto, para evitar colisiones con futuras operaciones.
                  </p>
                        
               </li>
               <li class="listitem">
                          
                  <p><span class="bold"><strong>Automatizaci&oacute;n del proceso</strong></span>:
                             intentar que el proceso sea lo m&aacute;s limpio posible para el
                             programador.
                  </p>
                        
               </li>
            </ul>
         </div>
         
             
         <p>Teniendo en cuenta estas consideraciones, el framework ha
                implementado una clase y una serie de m&eacute;todos con la intenci&oacute;n de
                facilitar el proceso al programador. Hay que destacar que un salto puede
                ser tan simple como indicar una URL en el actionForward correspondiente;
                pero con ello perderiamos todo control sobre el retorno (no podr&iacute;amos
                garantizar la "limpieza" de la SESSION).
         </p>
         
             
         <div class="section" title="4.4.1. Implementaci&oacute;n">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e3793"></a>4.4.1. Implementaci&oacute;n
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <p>Vamos a implementar un ejemplo. Tenemos un mantenimiento tabular
                     en el que vamos a acumular fila a fila una serie de aspirantes a los que
                     les queremos realizar una entrevista grupal. Estos aspirantes se
                     obtienen a trav&eacute;s de otra ventana (tambi&eacute;n tabular) en la que podemos
                     buscar los aspirantes por sus perfiles y seleccionarlos para la
                     entrevista. Una vez seleccionados los aspirantes deseados, se pulsa al
                     bot&oacute;n "Citar para entrevista" disparando el proceso (env&iacute;o de correos,
                     inserci&oacute;n en el planning del entrevistador, ...).
            </p>
            
                  
            <p>Ficheros implicados:</p>
            
                  
            <div class="table"><a name="d4e3797"></a><p class="title"><b>Tabla 4.1. Ficheros implicados en implementaci&oacute;n</b></p>
               <div class="table-contents">
                          
                  
                          
                  <table summary="Ficheros implicados en implementaci&oacute;n" border="1">
                     <colgroup>
                        <col width="25%">
                        <col width="25%">
                        <col width="25%">
                        <col width="25%">
                     </colgroup>
                     <thead>
                        <tr>
                           <th align="center">clase manejadora</th>
                           <th align="center">view</th>
                           <th align="center">plantilla tpl</th>
                           <th align="center">descripci&oacute;n</th>
                        </tr>
                     </thead>
                     <tbody>
                        <tr>
                           <td>GeneradorEntrevistas.php</td>
                           <td>p_generadorEntrevistas.php</td>
                           <td>p_generadorEntrevistas.tpl</td>
                           <td>Generador de entrevistas. Origen del salto</td>
                        </tr>
                        <tr>
                           <td>Aspirantes.php</td>
                           <td>p_aspirantes.php</td>
                           <td>p_aspirantes.tpl</td>
                           <td>Mantenimiento de aspirantes.</td>
                        </tr>
                     </tbody>
                  </table>
                        
               </div>
            </div><br class="table-break">
            
                  
            <p>Dando por hecho la creaci&oacute;n de los dos mantenimientos vamos a ir,
                     paso a paso, indicando como implementar el salto. En primer lugar,
                     tenemos que ubicar un punto de disparo de la acci&oacute;n de salto. Puede ser
                     bien un bot&oacute;n cl&aacute;sico:
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">{CWBoton id="saltoVisualizar" imagen="49" texto="SALTO" class="boton" accion="saltar"}</pre>
                     </div>
            
                  
            <p>o un bot&oacute;n tooltip:</p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">{CWBotonTooltip imagen="39" titulo="+" funcion="saltar" actuaSobre="ficha"}</pre>
                     </div>
            
                  
            <p>Ahora, tenemos que crear en la clase manejadora origen del salto
                     (GeneradorEntrevistas), un m&eacute;todo que gestione el salto (si se debe
                     saltar o no; si pasa par&aacute;metros). En este caso el framework proporciona
                     un m&eacute;todo para tal uso <span class="bold"><strong>saltoDeVentana</strong></span>:
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">public function saltoDeVentana($objDatos, $objSalto){        
    //Nombre de la claseM destino del salto
    $objSalto-&gt;<span class="bold"><strong>setNameTargetClass</strong></span>('Aspirantes');
    //Nombre de la accion de entrada a la ventana
    $objSalto-&gt;<span class="bold"><strong>setAccion</strong></span>('iniciarVentana');  
    //Nombre de la accion de retorno
    $objSalto-&gt;<span class="bold"><strong>setAccionRetorno</strong></span>('iniciarVentana');
    //Parametro: numero maximo de seleccionables
    $objSalto-&gt;<span class="bold"><strong>setParam</strong></span>('numeroMaxSeleccionable',5);
    return 0;    
}
</pre>
                     </div>
            
                  
            <p>Como se puede ver, por un lado tenemos los datos relativos a la
                     pantalla (objDatos) y por otro, los relativos al salto. El objeto salto
                     es el que se deber&aacute; configurar, para indicar la clase destino del salto,
                     <span class="bold"><strong><span class="bold"><strong>setNameTargetClass</strong></span>()</strong></span>, con el m&eacute;todo
                     <span class="bold"><strong>getNameSourceClass()</strong></span> podremos obtener
                     el nombre de la clase origen, la acci&oacute;n de entrada en la nueva ventana
                     (el mapeo correspondiente), <span class="bold"><strong>setAccion()</strong></span>, tambi&eacute;n se estable la acci&oacute;n de
                     retorno a la ventana origen con <span class="bold"><strong>setAccionRetorno()</strong></span>. Tambi&eacute;n se pueden a&ntilde;adir
                     par&aacute;metros al salto usando el m&eacute;todo <span class="bold"><strong>setParam()</strong></span>.
            </p>
            
                  
            <p>Este c&oacute;digo, redireccionar&aacute; la ejecuci&oacute;n hacia la clase
                     <span class="emphasis"><em>Aspirantes</em></span> entrando con la acci&oacute;n
                     <span class="emphasis"><em>iniciarVentana</em></span>. Esto implica que en el fichero de
                     mapeos (mappings.php) tenemos que definir el _AddMapping y los
                     _AddForwards correspondientes.
            </p>
            
                  
            <p>Ahora, en la clase destino del salto, debemos recoger la
                     informaci&oacute;n transmitida en el salto. Para ello, en el constructor
                     a&ntilde;adiremos el siguiente c&oacute;digo:
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">//Comprobamos si hay salto
$objSalto = IgepSession::<span class="bold"><strong>damePanel</strong></span>('saltoIgep');
if(is_object($objSalto)){
    $this-&gt;parametros = $objSalto-&gt;<span class="bold"><strong>getParams</strong></span>();
}</pre>
                     </div>
            
                  
            <p>Tenemos que acceder a la zona de la SESSION donde el framework
                     almacena la informaci&oacute;n del salto y recuperar el objeto con <span class="bold"><strong>damePanel('saltoIgep')</strong></span> y con <span class="bold"><strong>getParams()</strong></span> obtendremos los par&aacute;metros que nos
                     pasar&aacute; la clase origen.
            </p>
            
                  
            <p>Una vez realizado el salto, vamos a indicar como se realiza el
                     retorno. Para ello primero vamos a ver en la tpl como indicar que vamos
                     a lanzar una acci&oacute;n de retorno. En nuestro caso hemos a&ntilde;adido dos
                     botones que controlan el retorno, uno acumula los seleccionados, el otro
                     cancela la operaci&oacute;n. En ambos casos la acci&oacute;n es volver, los
                     diferenciamos a trav&eacute;s del id.
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">{CWBoton id="acumular" imagen="49" texto="ACUMULAR" class="boton" accion="volver"}
{CWBoton id="cancelarAcumular" imagen="42" texto="CANCELAR" class="boton" accion="volver"}</pre>
                     </div>
            
                  
            <p>Este est&iacute;mulo se recibir&aacute; en la clase objeto del salto (en nuestro
                     ejemplo Aspirantes). En ella debemos sobre escribir el m&eacute;todo
                     regresoAVentana:
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">public function regresoAVentana($objDatos, $objSalto){
    if($objSalto-&gt;<span class="bold"><strong>getId</strong></span>()=='acumular'){
        //Recogemos los datos seleccionados por el usuario en pantalla
        $m_datos = $objDatos-&gt;getAllTuplas('seleccionar');
        $objSalto-&gt;setParam('nuevosAspirantes',$m_datos);
        $objSalto-&gt;setAccionRetorno('acumular');
    }
    return 0;
}</pre>
                     </div>
            
                  
            <p>En nuestro ejemplo, en el caso de que el usuario haya seleccionado
                     aspirantes y haya pulsado acumular, volveremos a la clase con la acci&oacute;n
                     acumular, podremos saber si se ha pulsado el bot&oacute;n Acumular obteniendo
                     su id con el m&eacute;todo <span class="bold"><strong>getId()</strong></span>. En caso
                     contrario volveremos con la acci&oacute;n que se program&oacute; en el salto
                     (iniciarVentana). Por supuesto, la clase origen del salto, tiene que
                     tener en el fichero de mapeo el <span class="emphasis"><em>_AddMapping</em></span> y los
                     <span class="emphasis"><em>_AddForwards</em></span> correspondientes (en nuestro caso
                     GeneradorEntrevistas__acumular y
                     GeneradorEntrevistas__iniciarVentana).
            </p>
            
                  
            <p>Hay una serie de m&eacute;todos que no se han utilizado en este ejemplo
                     pero que pueden ser de utilidad. Entre ellos destacamos el m&eacute;todo
                     getNameSourceClass que devuelve el nombre de la clase origen del
                     salto.
            </p>
            
                  
            <p>Finalmente, en la clase origen del salto, tenemos que configurar
                     el regreso del mismo. En el caso de un regreso por cancelaci&oacute;n de
                     acci&oacute;n, no tenemos que hacer nada, ya que se trata de una acci&oacute;n
                     gen&eacute;rica del framework (iniciarVentana). En el caso de un regreso para
                     acumular, se ha decidido realizar una acci&oacute;n no gen&eacute;rica: una acci&oacute;n
                     particular. Se trata de la acci&oacute;n GeneradorEntrevistas__acumular.
            </p>
            
                  
            <p>Para tratarla tenemos que incorporar el siguiente c&oacute;digo.</p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">public function accionesParticulares($accion, $objDatos) {
    switch ($accion) {
        case 'acumular':
            $salto = IgepSession::damePanel('saltoIgep');
            $nuevos = $salto-&gt;getParam('nuevosAspirantes');
            $this-&gt;acumularAspirantes($nuevos);
            $actionForward = $objDatos-&gt;getForward('correcto');
            break;
        }
        return $actionForward;
}</pre>
                     </div>
            
                  
            <p>En el m&eacute;todo acumularAspirantes, se realizar&aacute;n las acciones
                     pertinentes seg&uacute;n la l&oacute;gica del caso de uso. En nuestro ejemplo
                     tendriamos que a&ntilde;adir los nuevos aspirantes a los seleccionados
                     previamente:
            </p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting">public function acumularAspirantes($nuevos) 
{
   $acumulados = $this-&gt;getResultadoBusqueda();
   if($acumulados == '')
      $acumulados = array();
   foreach($nuevos as $indice =&gt;$linea) 
   {
      $aspirante = array();
      $aspirante["dni"] = $linea["dni"]; 
      $aspirante["nombre"] = $linea["nombre"];
      ...
      array_push($acumulados,$aspirante); 
   }       
   $this-&gt;setResultadoBusqueda($acumulados);    

   // si en vez de mostrar los aspirantes seleccionados quisieramos modificarlos
   // directamente en la base de datos, luego podriamos refrescar la pantalla con:
   //$this-&gt;refreshSearch();
}</pre>
                     </div>
            
                  
            <p>Con esto ya tenemos un ejemplo entero de saltos. Como antes
                     indic&aacute;bamos, en futuras versiones este mecanismo se revisar&aacute; y
                     mejorar&aacute;.
            </p>
                
         </div>
           
      </div>
      <div class="navfooter">
         <hr>
         <table width="100%" summary="Navigation footer">
            <tr>
               <td width="40%" align="left"><a accesskey="p" href="ch04s03.html">Anterior</a>&nbsp;
               </td>
               <td width="20%" align="center"><a accesskey="u" href="ch04.html">Subir</a></td>
               <td width="40%" align="right">&nbsp;<a accesskey="n" href="ch04s05.html">Siguiente</a></td>
            </tr>
            <tr>
               <td width="40%" align="left" valign="top">4.3. Tratamiento de ficheros&nbsp;</td>
               <td width="20%" align="center"><a accesskey="h" href="indice.html">Inicio</a></td>
               <td width="40%" align="right" valign="top">&nbsp;4.5. Carga din&aacute;mica de clases</td>
            </tr>
         </table>
      </div>
   </body>
</html>